Repository navigation
Conversation
Theme app extensions can now list the origins they contact in
shopify.extension.toml:
[extensions.capabilities.network_access]
allowed_sources = ["https://api.example.com", "https://*.example-cdn.com"]
Each entry must be an HTTPS origin with no path, query or fragment.
Entries are normalized and deduplicated, and a list can have up to 20
origins. The theme deploy config includes capabilities only when the
table is declared, so existing payloads don't change. UI extensions keep
the boolean network_access.
Use a wildcard example under example.com in the error hint, and test empty labels, trailing dots, newlines and single-label wildcards.
Knip flags it as unused outside the module.
pt2pham
approved these changes
Oct 24, 2026
pt2pham
left a comment
Contributor
There was a problem hiding this comment.
I didn't give this a tophat but the proposed changes make sense to me to just include this as a field for theme extensions
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
Needs server support before release. The platform rejects unknown keys in a theme app extension's deploy config today, so deploying an extension that declares
[extensions.capabilities.network_access]fails until the server acceptscapabilities.network_access.allowed_sources. Extensions that don't declare it send the same payload as before and aren't affected.WHY are these changes introduced?
Theme app extensions load scripts and make requests on storefronts, but there's no way for them to say which origins they contact. Declaring them lets the platform build a storefront Content Security Policy for each extension, starting in report-only mode. Undeclared origins may be reported now and blocked later.
UI extensions (checkout, customer accounts) already use a boolean
capabilities.network_access. They run sandboxed, so they keep the boolean. Theme app extensions use the same key as a table.WHAT is this pull request doing?
Theme app extensions can declare the origins they contact in
shopify.extension.toml:network_accessis a table withallowed_sources. The sharedCapabilitiesSchemastill accepts only a boolean, so UI extensions don't change. Only the TypeScript type of the shared field is widened so the theme config still fitsBaseConfigType. The dev payload now readsnetwork_access === true, which is the same for booleans.deployConfigaddscapabilities: {network_access: {allowed_sources: [...]}}next totheme_extensiononly when the table is declared. Otherwise the payload stays{theme_extension: {files: {}}}, byte for byte.Validation rules (each entry in
allowed_sources):https://only, with a host and an optional port. No path, query, fragment or credentials, sohttp://, scheme-less values, CSP keywords like'self', and*are rejected.localhostis rejected). Labels can't start or end with a hyphen, and the host is at most 253 characters. A numeric last label is rejected, which rules out IP addresses.*.wildcard is allowed, and it must cover at least two labels (https://*.cdn.example.comis fine, buthttps://*.comandhttps://api.*.example.comaren't). CSP host sources support this form, and extensions often load from CDN subdomains.:443is dropped, and other ports are kept./is dropped, and duplicates are removed after normalization. The normalized list is what gets deployed.Omitted vs. empty:
[extensions.capabilities.network_access]tableallowed_sources = []allowed_sources: []allowed_sourcesallowed_sources is required. Use an empty list if your extension contacts no other origins.network_access = true/false(the UI extension boolean)app devneeds no separate change: dev sessions build the app manifest from the samedeployConfig, so declared sources reach the server there too, and are subject to the same server-support caveat.There's no generated JSON schema or docs for extension TOML in this repo. The field should be documented in the theme app extension configuration docs once the server supports it.
Tests (
packages/app):pnpm vitest run src/cli/models/extensions/specifications/theme.test.ts: 36 tests pass. They cover valid origins and normalization, the empty list, omitted, the ignored boolean, missingallowed_sources, wrong types, http, no scheme, path, query, fragment, credentials, wildcard placement, single-label hosts, empty labels, trailing dots, newlines, IPs, ports, CSP keywords and injection, the 20-origin limit, deploy config with and without the table, and UI extensions keeping the boolean (and rejecting the table).loader.test.ts: new test that loads a theme extension TOML with the table and checks the deploy config.src/cli/models/extensions/specifications/,extension-instance,dev/extension/payload,app/loader,load-specificationsandservices/context/: 34 files, 605 tests pass.pnpm tsc --noEmit,pnpm eslinton changed files andprettier --check: clean.How to manually test your changes?
shopify app buildorshopify app deploy. The config loads, and the deploy payload includes the normalizedallowed_sources. Deploy succeeds only once the server supports the field.http://api.example.comorhttps://api.example.com/path. Loading fails with the invalid-entry error.{"theme_extension":{"files":{}}}as before.Post-release steps
Document
[extensions.capabilities.network_access] allowed_sourcesfor theme app extensions once the server supports it.Checklist
patchfor bug fixes ·minorfor new features ·majorfor breaking changes) and added a changeset withpnpm changeset add